import sys, os
import requests
import xadmin

from django.contrib.admin.models import LogEntry, CHANGE
from django.contrib import admin
from django.contrib.admin.options import get_content_type_for_model
from django.contrib.auth import get_permission_codename
from django.urls import reverse
from django.utils.encoding import force_text
from django.utils.html import format_html
from xadmin.filters import RelatedFieldListFilter, manager
from xadmin.layout import Fieldset, Row, Container

from .adminforms import PostAdminForm
from .models import Post, Category, Tag

# Register your models here.

# 自定义过滤器
from typeidea.custom_site import custom_site

# sys.path.append(os.path.dirname(__file__) + os.sep + '../')
from typeidea.base_admin import BaseOwnerAdmin

sys.path.append('../')

PERMISSION_API = "http://permission.sso.com/has_perm?user={}&perm_code={}"


class CategoryOwnerFilter(RelatedFieldListFilter):
    """自定义过滤器只展示当前用户分类"""
    title = '分类过滤器'
    # 查询时URL参数的名字，比如查询分类id为1的内容时，URL后面的Query部分是?owner_category=1
    parameter_name = 'owner_category'

    # 返回要展示的内容和查询用的id
    # def lookups(self, request, model_admin):
    #     return Category.objects.filter(owner=request.user).values_list('id', 'name')  # name就是展示用的字段
    #
    # # 根据URL Query的内容返回列表页数据。比如URL最后的Query是?owner_category=1,那么这里拿到的self.value()就是1
    # # 此时就会根据1来过滤QuerySet，QuerySet是列表页所有展示数据的集合。
    # def queryset(self, request, queryset):
    #     category_id = self.value()
    #     if category_id:
    #         return queryset.filter(category_id=self.value())
    #     return queryset
    @classmethod
    def test(cls, field, request, params, model, admin_view, field_path):
        return field.name == 'category'

    def __init__(self, field, request, params, model, model_admin, field_path):
        super().__init__(field, request, params, model, model_admin, field_path)
        # 重新获取lookup_choices，根据owner过滤
        self.lookup_choices = Category.objects.filter(owner=request.user).values_list('id', 'name')


manager.register(CategoryOwnerFilter, take_priority=True)


# 在同一页面编辑关联数据
class PostInline(admin.TabularInline):  # StackedInline 样式不同
    # fields = ('title', 'desc')
    form_layout = (
        Container(
            Row("title", "desc"),
        )
    )
    extra = 1
    model = Post  # 必须有外键关联


@xadmin.sites.register(Category)
class CategoryAdmin(BaseOwnerAdmin):
    list_display = ('name', 'status', 'is_nav', 'created_time', 'post_count')
    fields = ('name', 'status', 'is_nav')
    inlines = [PostInline, ]

    # 保存数据前，把owner字段设定为当前的登录用户，做法就是重写ModelAdmin的save_model方法
    # 其作用是保存数据到数据库中
    # obj是当前要保存的对象，form是页面提交过来的表单之后的对象，change用于标志本次保存的数据是新增的还是更新的
    # request.user就是当前已经登录的用户，未登录的的情况下，通过request.user拿到的是匿名对象
    # def save_model(self, request, obj, form, change):
    #     obj.owner = request.user
    #     return super(CategoryAdmin, self).save_model(request, obj, form, change)

    # 展示该分类下有多少篇文章
    def post_count(self, obj):
        return obj.post_set.count()

    post_count.short_description = '文章数量'


@xadmin.sites.register(Tag)
class TagAdmin(BaseOwnerAdmin):
    list_display = ('name', 'status', 'created_time')
    fields = ('name', 'status')

    # def save_model(self, request, obj, form, change):
    #     obj.owner = request.user
    #     return super(TagAdmin, self).save_model(request, obj, form, change)


@xadmin.sites.register(Post)
class PostAdmin(BaseOwnerAdmin):
    form = PostAdminForm
    list_display = [
        'title', 'category', 'status',
        'created_time', 'owner', 'operator'  # operator是自定义字段
    ]
    list_display_links = []  # 用来配置那些字段可以作为链接，点击他们，可以进入编辑页面

    # list_filter = [CategoryOwnerFilter, ]  # 页面过滤器，需要通过哪些字段来过滤列表页
    list_filter = ['category']  # 页面过滤器，需要通过哪些字段来过滤列表页
    search_fields = ['title', 'category__name']  # 配置搜索字段
    # 动作相关的配置，是否展示在顶部，或者是否展示在底部
    actions_on_top = True
    actions_on_bottom = True

    # 编辑页面,保存、编辑、编辑并新建按钮是否在顶部展示
    save_on_top = True
    exclude = ['owner', ]

    # 多对多字段的展示配置，横向展示和纵向展示
    # filter_horizontal = ('tag', )
    # filter_vertical = ('tag', )
    # 控制编辑页面布局
    # fieldsets = (
    #     ('基础配置', {
    #         'description': '基础配置描述',
    #         'fields': (
    #             ('title', 'category'),
    #             'status',
    #         ),
    #     }),
    #     ('内容', {
    #         'description': '内容描述',
    #         'fields': (
    #             'desc',
    #             'content',
    #         ),
    #     }),
    #     ('额外信息', {
    #         'description': '额外信息描述',
    #         'classes': ('wide',),  # 给配置的板块加上CSS样式，django默认支持的是
    #         'fields': ('tag',),
    #     })
    # )
    form_layout = (
        Fieldset(
            '基础信息',
            Row("title", "category"),
            'status',
            'tag',
        ),
        Fieldset(
            '内容信息',
            'desc',
            'is_md',
            'content_ck',
            'content_md',
            'content',
        )
    )

    # 自定义函数可以返回HTML，但是需要通过format_html函数处理，reverse解析URL地址
    def operator(self, obj):
        return format_html(  # Django中的常用的函数format_html,用于格式化生成html模板
            '<a href="{}">编辑</a>',
            # reverse('admin:blog_post_change', args=(obj.id,))
            reverse('xadmin:blog_post_change', args=(obj.id,))  # 修改了admin的继承方式
        )

    # 指定表头的展示文案
    operator.short_description = '操作'

    # admin的权限逻辑以及SSO登录
    # def has_add_permission(self, request):
    #     opts = self.opts
    #     codename = get_permission_codename('add', opts)
    #     perm_code = "%s.%s" % (opts.app_label, codename)
    #     resp = requests.get(PERMISSION_API.format(request.user.username, perm_code))
    #     if resp.status_code == 200:
    #         return True
    #     else:
    #         return False

    # 自定义日志
    # def log_change(self, request, object, message):
    #     return LogEntry.objects.log_action(
    #         user_id=request.user.pk,
    #         content_type_id=get_content_type_for_model(object).pk,
    #         object_id=object.pk,
    #         object_repr=force_text(object),
    #         action_flag=CHANGE,
    #         change_message=message,
    #     )

    # 自定义静态资源引入,我们可以通过自定义media类来往页面上增加想要添加的JavaScript以及CSS资源
    # class Media:
    #     css = {
    #         'all': ("https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/"
    #                 "bootstrap.min.css",),
    #     }
    #     js = ('https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/js/bootstrap.bundle.js',)
    @property
    def media(self):
        media = super().media
        media.add_js(['https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/js/bootstrap.bundle.js'])
        media.add_css({
            'all': ('https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css',), })
        return media


# 在admin页面上查看操作日志
# @admin.register(LogEntry, site=custom_site)
# class LogEntryAdmin(admin.ModelAdmin):
#     list_display = ['object_repr', 'object_id', 'action_flag', 'user', 'change_message']
